Crate exonum_testkit [] [src]

Testkit for Exonum blockchain framework, allowing to test service APIs synchronously and in the same process as the testkit.

Example

#[macro_use]
extern crate exonum;
#[macro_use]
extern crate exonum_testkit;
extern crate serde_json;

use exonum::crypto::{gen_keypair, Hash, PublicKey, CryptoHash};
use exonum::blockchain::{Block, Schema, Service, Transaction, TransactionSet, ExecutionResult};
use exonum::explorer::BlocksRange;
use exonum::messages::{Message, RawTransaction};
use exonum::storage::{Snapshot, Fork};
use exonum::encoding;
use exonum_testkit::{ApiKind, TestKitBuilder};

// Simple service implementation.

const SERVICE_ID: u16 = 1;

transactions! {
    TimestampingTransactions {
        const SERVICE_ID = SERVICE_ID;

        struct TxTimestamp {
            from: &PublicKey,
            msg: &str,
        }
    }
}

struct TimestampingService;

impl Transaction for TxTimestamp {
    fn verify(&self) -> bool {
        self.verify_signature(self.from())
    }

    fn execute(&self, _fork: &mut Fork) -> ExecutionResult {
        Ok(())
    }
}

impl Service for TimestampingService {
    fn service_name(&self) -> &str {
        "timestamping"
    }

    fn state_hash(&self, _: &Snapshot) -> Vec<Hash> {
        Vec::new()
    }

    fn service_id(&self) -> u16 {
        SERVICE_ID
    }

    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
        let tx = TimestampingTransactions::tx_from_raw(raw)?;
        Ok(tx.into())
    }
}

fn main() {
    // Create testkit for network with four validators.
    let mut testkit = TestKitBuilder::validator()
        .with_validators(4)
        .with_service(TimestampingService)
        .create();

    // Create few transactions.
    let keypair = gen_keypair();
    let tx1 = TxTimestamp::new(&keypair.0, "Down To Earth", &keypair.1);
    let tx2 = TxTimestamp::new(&keypair.0, "Cry Over Spilt Milk", &keypair.1);
    let tx3 = TxTimestamp::new(&keypair.0, "Dropping Like Flies", &keypair.1);
    // Commit them into blockchain.
    testkit.create_block_with_transactions(txvec![
        tx1.clone(), tx2.clone(), tx3.clone()
    ]);

    // Add a single transaction.
    let tx4 = TxTimestamp::new(&keypair.0, "Barking up the wrong tree", &keypair.1);
    testkit.create_block_with_transaction(tx4.clone());

    // Check results with schema.
    let snapshot = testkit.snapshot();
    let schema = Schema::new(&snapshot);
    assert!(schema.transactions().contains(&tx1.hash()));
    assert!(schema.transactions().contains(&tx2.hash()));
    assert!(schema.transactions().contains(&tx3.hash()));
    assert!(schema.transactions().contains(&tx4.hash()));

    // Check results with api.
    let api = testkit.api();
    let response: BlocksRange = api.get(ApiKind::Explorer, "v1/blocks?count=10");
    let (blocks, range) = (response.blocks, response.range);
    assert_eq!(blocks.len(), 3);
    assert_eq!(range.start, 0);
    assert_eq!(range.end, 3);

    api.get::<serde_json::Value>(
        ApiKind::Explorer,
        &format!("v1/transactions/{}", tx1.hash().to_string()),
    );
}

Re-exports

pub use compare::ComparableSnapshot;

Modules

compare

Routines for comparison between 2 states.

Macros

txvec

Creates a Vec<Box<Transaction>> from the given transactions, or other objects implementing the Into<Box<Transaction>> trait.

Structs

TestKit

Testkit for testing blockchain services. It offers simple network configuration emulation (with no real network setup).

TestKitApi

API encapsulation for the testkit. Allows to execute and synchronously retrieve results for REST-ful endpoints of services.

TestKitBuilder

Builder for TestKit.

TestNetwork

Emulated test network.

TestNetworkConfiguration

A configuration of the test network.

TestNode

An emulated node in the test network.

Enums

ApiKind

Kind of public or private REST API of an Exonum node.